﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Yunchang.ILUI
{
    public class UIPageManager : Manager<UIPageManager>,ILateUpdate
    {
        #region Delegates & Events

        public delegate void OnPageCallback(UIPage page);
        /// <summary>
        /// 页面打开
        /// </summary>
        public event OnPageCallback onPageOpenEvent;
        /// <summary>
        /// 页面关闭
        /// </summary>
        public event OnPageCallback onPageCloseEvent;
        /// <summary>
        /// 页面显示隐藏调用
        /// </summary>
        public event Action<UIPage, bool> onPageActiveChangeEvent;

        #endregion

        public UILayer[] LayerArray { get; private set; }
        public Camera uiCamera { get; private set; }

        private Dictionary<int, UILayer> mLayerMap = new Dictionary<int, UILayer>();
        /// <summary>
        /// 当前开着的UI面板
        /// </summary>
        private Dictionary<string, UIPage> pageMap = new Dictionary<string, UIPage>();

        /// <summary>
        /// 循环变量使用
        /// </summary>
        private UIPage[] UpdateUIPageArray = new UIPage[8];

        //所有UI界面的父节点
        private RectTransform mUIRoot;

        //所有UI界面的父节点
        private Transform mPageRoot;

        //头顶板父节点
        private Transform mHeadBoardRoot;

        //waitBox 应该处理异常情况，以防资源错误情况下 卡死。 需要有超时返回
        private GameObject waitBox = null;
        private GameObject UIMadoBox = null;
        private bool mUIMapIsChange = false;

        //private UIFitTool
        bool myInited = false;

        private Vector2 mUIRootSize = Vector2.zero;

        public Vector2 uiRootSize
        {
            get {
                if (mUIRootSize == Vector2.zero && mUIRoot != null)
                    mUIRootSize = new Vector2(mUIRoot.rect.width, mUIRoot.rect.height);
                return mUIRootSize;
            }
        }
        public override void OnInit()
        {
            base.OnInit();
        }

        public void InitAsset()
        {
            var gameMain = mainRoot.transform;
            mUIRoot = gameMain.Find("UIRoot").GetComponent<RectTransform>();
            CanvasScaler cs = mUIRoot.GetComponent<CanvasScaler>();
            mPageRoot = CreatRectTransform(mUIRoot,"PageRoot");
            mHeadBoardRoot = CreatRectTransform(mUIRoot, "HeadBoardRoot");
            GameObject screenFrame = mUIRoot.Find("UIPageScreenFrame").gameObject;

            UIMadoBox = mUIRoot.Find("waitBox").GetChild(0).gameObject;

            Transform waitBoxTrans = mUIRoot.Find("waitBox");
            waitBox = waitBoxTrans.GetChild(0).gameObject;
            waitBoxTrans.GetComponent<RectTransform>().SetSiblingIndex(mUIRoot.childCount - 1);

            uiCamera = mUIRoot.GetComponentInChildren<Camera>();
            BuildUILayer();

            //默认面板
            OpenPage("UIHeadBoardPanel");
            myInited = true;

            //_myFitTool = new UIFitTool();
            //_myFitTool.Init(screenFrame, cs);
        }

        public static RectTransform CreatRectTransform(Transform parent, string name)
        {
            GameObject tmpObj = new GameObject(name);
            RectTransform rectForm = tmpObj.AddComponent<RectTransform>();
            rectForm.SetParent(parent);
            rectForm.anchorMin = new Vector2(0, 0);
            rectForm.anchorMax = new Vector2(1, 1);
            rectForm.offsetMin = new Vector2(0,0);
            rectForm.offsetMax = new Vector2(0, 0);
            rectForm.localScale = Vector3.one;
            return rectForm;
        }

        /// <summary>
        /// 屏蔽操作
        /// </summary>
        /// <param name="showAnimat"></param>
        public void ShowWaitBox(bool showAnimat)
        {
            waitBox.SetActive(true);
        }

        public void CloseWaitBox()
        {
            waitBox.SetActive(false);
        }

        private void BuildUILayer()
        {
            Clear();
            mLayerMap.Clear();

            //TODO 获取所有层
            List<TableUILayer> LayerList = new List<TableUILayer>();
            if (LayerList == null || LayerList.Count < 1) return;

            LayerList.Sort((a, b) => {
                return a.layer.CompareTo(b.layer);
            });

            int layerCount = LayerList.Count;
            LayerArray = new UILayer[layerCount];

            TableUILayer layerTable;
            RectTransform parentTrans;
            int countDepth = 0;
            UILayer uiLayer;

            for (int i = 0; i < layerCount; i++)
            {
                layerTable = LayerList[i];
                Transform thisParent;
                if (layerTable.name == "GT_HeadBoard")
                    thisParent = mHeadBoardRoot;
                else
                    thisParent = mPageRoot;

                parentTrans = CreatRectTransform(thisParent, layerTable.name);
                //把 除了头顶版以外的其他组放在同一个节点下 ，以方便统一设置显隐

                parentTrans.localScale = Vector3.one;
                parentTrans.localPosition = Vector3.zero;

                uiLayer = new UILayer(i, countDepth, layerTable, parentTrans);
                LayerArray[i] = uiLayer;
                mLayerMap.Add(layerTable.id, uiLayer);
                countDepth += layerTable.thickness;

            }

        }

        public void Clear()
        {
            List<string> pageToClose = new List<string>();
            for (var tmp = pageMap.GetEnumerator();tmp.MoveNext();)
            {
                string pageName = tmp.Current.Value.ID;

                //头顶板界面不需要关闭
                if (pageName == "UIHeadBoardPanel")
                {
                    continue;
                }
                pageToClose.Add(pageName);
            }

            for (int i = 0; i < pageToClose.Count; i++)
            {
                ClosePage(pageToClose[i]);
            }
        }

        public UILayer GetUILayer(int type)
        {
            UILayer uiLayer = null;
            mLayerMap.TryGetValue(type,out uiLayer);
            return uiLayer;
        }

        public bool IsOpen(string id)
        {
            return pageMap.ContainsKey(id);
        }

        Dictionary<string, UIPage> Openning = new Dictionary<string, UIPage>();

        public void OpenPageArgs(string id, params object[] arg)
        {
            OpenPage(id, arg);
        }

        /// <summary>
        /// Important 
        /// </summary>
        /// <param name="pageName"></param>
        /// <param name="arg"></param>
        public void OpenPage(string pageName, object arg = null)
        {
            //TODO GetPage Data
            TablePage tablePage = new TablePage();
            if (tablePage == null)
            {
                GLog.Error("TablePage is not find !={0}" , pageName);
                return;
            }

            UILayer uiLayer = GetUILayer(tablePage.layer);
            if (uiLayer == null || uiLayer.uiStackTransform == null)
            {
                //层级配置不对
                GLog.Error("Error !! OpenUI : uiLayer is null id = {0}", pageName);
                return;
            }

            if (Openning.ContainsKey(pageName))
            {
                return;
            }

            UIPage ui = null;
            if (pageMap.TryGetValue(pageName, out ui))
            {
                ui.OnRefresh(arg);
                return;
            }

            //TODO 对遥感做处理
            if (uiLayer.table.joystickUp == 1) { }

            //对Lua做处理
            if (!string.IsNullOrEmpty(tablePage.LuaCtrl) && tablePage.LuaCtrl != "-1" && tablePage.LuaCtrl != "none")
            {
                ui = new UIPage();
                XLua.LuaTable table = LuaManager.Ins.GetTable(tablePage.LuaCtrl);
                ui.SetTalbeLua(table);
            }
            else
            {
                Type t = Type.GetType(tablePage.CSharpCtrl);
                if (t == null)
                {
                    GLog.Error("配置的类：{0} 未在程序集中找到！",tablePage.CSharpCtrl);
                    return;
                }

                ui = Activator.CreateInstance(t) as UIPage;
                if (ui == null)
                {
                    GLog.Error("配置的 {0} 非 UIPage 类型!",tablePage.CSharpCtrl);
                    return;
                }
            }
            //TODO 需要做延时处理
            ShowWaitBox(true);
            Openning.Add(pageName, ui);
            ui.Open(tablePage, uiLayer, OnOpenPageComplete, PageRequitClose, PageActiveChange, arg);
        }

        private void PageActiveChange(UIPage page, bool active)
        {
            if (onPageActiveChangeEvent != null)
                onPageActiveChangeEvent(page,active);
        }

        private void PageRequitClose(string id)
        {
            ClosePage(id);
        }

        private void OnOpenPageComplete(UIItem item)
        {
            UIPage page = item as UIPage;

            if (!Openning.ContainsKey(page.ID))//加载中关了
            {
                page.ExciteDestroy();
                UILayer uiLayer = GetUILayer(page.table.layer);
                uiLayer.RemoveUIPage(page.ID);
                return;
            }

            Openning.Remove(page.ID);
            if (!pageMap.ContainsKey(page.ID))
            {
                pageMap.Add(page.ID, page);
                mUIMapIsChange = true;
            }

            if (onPageOpenEvent != null)
            {
                onPageOpenEvent(page);
            }

            UIMadoBox.SetActive(page.table.modal == 1);
            GLog.Log("Open Page id = {0} ",page.ID);
        }

        public void ClosePage(string pageName)
        {
            ClosePage(pageName, true);
        }

        public void ClosePage(string id, bool RemoveFromLayer)
        {
            UIPage ui = null;
            if (Openning.ContainsKey(id))
            {
                Openning.Remove(id);
                return;
            }

            if (pageMap.TryGetValue(id, out ui))
            {
                pageMap.Remove(ui.ID);

                int layer = ui.table.layer;
                ui.ExciteDestroy();

                if (RemoveFromLayer)
                {
                    UILayer uiLayer = GetUILayer(layer);
                    uiLayer.RemoveUIPage(id);
                }

                if (onPageCloseEvent != null)
                {
                    onPageCloseEvent(ui);
                }

                GLog.Log("Close Page id = {0}", id);
                mUIMapIsChange = true;
            }
        }

        public T GetUIPage<T>(string uiName) where T : UIPage
        {
            UIPage page = null;
            pageMap.TryGetValue(uiName, out page);
            return page as T;
        }
        
        /// <summary>
        /// UI 统一LateUpdate
        /// </summary>
        /// <param name="deltaTime"></param>
        public void OnLateUpdate(float deltaTime)
        {
            if (!myInited) return;
            int count = pageMap.Count;
            if (UpdateUIPageArray.Length < count)
            {
                UpdateUIPageArray = new UIPage[count];
            }

            if (mUIMapIsChange)
            {
                pageMap.Values.CopyTo(UpdateUIPageArray, 0);
                mUIMapIsChange = false;
            }

            for (int i = 0; i < count; i++)
            {
                UIPage ui = UpdateUIPageArray[i];
                if (ui != null && ui.inited)
                    ui.Update();
            }

            if (waitBox != null && waitBox.activeSelf && Openning.Count < 1 /* net lock*/)
            {
                CloseWaitBox();
            }
        }

        public override void OnExitScene()
        {
            int count = pageMap.Count;
            if (UpdateUIPageArray.Length < count)
            {
                UpdateUIPageArray = new UIPage[count];
            }

            if (mUIMapIsChange)
            {
                pageMap.Values.CopyTo(UpdateUIPageArray,0);
                mUIMapIsChange = false;
            }

            for (int i = 0; i < count; i++)
            {
                UIPage ui = UpdateUIPageArray[i];
                if (ui != null && ui.inited)
                    ui.OnExitScene();
            }

            ClosePageWhileLoading();
        }
        public override void OnEnterScene()
        {
           
        }

        public void ClosePageWhileLoading()
        {
            if (pageMap == null || pageMap.Count == 0)
            {
                return;
            }

            List<UIPage> pagelist = new List<UIPage>();
            for (var e = pageMap.GetEnumerator(); e.MoveNext();)
            {
                string name = e.Current.Key;
                //TODO
                TablePage tablePage = new TablePage();
                if (tablePage == null || tablePage.loadingClose == 0)
                {
                    continue;
                }

                UIPage page = e.Current.Value;
                if (page == null)
                {
                    continue;
                }

                pagelist.Add(page);
            }

            if (pagelist != null && pagelist.Count != 0)
            {
                for (int i = 0; i < pagelist.Count; i++)
                {
                    UIPage page = pagelist[i];
                    if (page != null)
                    {
                        page.Close();
                    }
                }
            }
        }
    }
}